#include "Renderer.hpp"
#include "../Core/Window.hpp"
#include "../Core/Device.hpp"
#include "../Debug/Logger.hpp"
#include "Utils/Exceptions.hpp"

namespace red{
	Renderer::Renderer() : mEntityNumber(0), mLastFrameEntityNumber(0){

	}

	Renderer::~Renderer(){
	}

	void Renderer::Init(Device* pDevice){
		mDevice = pDevice;

		// Initialisation de GLEW sous Windows
		#ifdef REDWIN32
			glewExperimental = GL_TRUE;
			glewInit();

			if(!glewIsSupported("GL_VERSION_3_3"))
				throw Exception("GLEW : OpenGL Version 3.3 is not supported");
			else
				OmniLog << "OpenGL Version Supported : 3.3.0" << eol;
		#endif

		// Activation du Z-Depth
		glEnable(GL_DEPTH_TEST);
		glDepthFunc(GL_LESS);
		
		// BackColor
		glClearColor(1.f,0.8f,0.f,1.f);
		
		Window& window = mDevice->GetWindow();
		m3DProjectionMatrix.PerspectiveFOV(45, (f32)window.GetWidth() / (f32)window.GetHeight(), 0.1f, 1000.f);
		m2DProjectionMatrix.OrthoOffCenter(0,0,(f32)window.GetWidth(), (f32)window.GetHeight());

		// Entity Number drawn text
		mEntityNumberText.SetText(String("Entities : ")+mEntityNumber);
		mEntityNumberText.SetPosition(10,34);
		mEntityNumberText.SetColor(Color::White);
		mEntityNumberText.SetSize(12);		
	}
	
	void Renderer::BeginScene() const{
	    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	}
	
	void Renderer::Draw(VAO &pVao){
		mVAOList.push_back(&pVao);
	}

	void Renderer::Render(){
		mEntityNumber = 0;

		if(!mVAOList.empty())
			RenderVAOs();

	//	mWindow->GetWindow().myRenderer.myTextureIsValid = false;
	//	RenderTexts();
	}

	void Renderer::DrawVAO(VAO* pVao){
		pVao->Bind();
		glDrawElements(GL_TRIANGLES, pVao->GetIndexCount(), GL_UNSIGNED_INT, 0);
		pVao->UnBind();
	}
	
	void Renderer::RenderVAOs(){
		static Shader* currentShader;
		static VAO* currentObject;

		currentShader = s1;
		s1->Bind();
		currentObject = 0;
		
		for(mVAOListIt = mVAOList.begin(); mVAOListIt != mVAOList.end(); ++mVAOListIt){			
			// Get the current Object
			currentObject = (*mVAOListIt);			

	/*		// If the object possess a different shader, change it
			if(currentObject->GetShader() != currentShader){
				currentShader = currentObject->GetShader();
				currentShader->Bind();
			}
*/			
			// Send the Object matrices to the shader
		//	currentShader->SendMatrix4("ModelViewProjMatrix", m3DViewProjMatrix, VertexShader);
		//	currentShader->SendMatrix4("MM", currentObject->GetModelMatrix(), VertexShader);

			// Send the Object material to the shader
			//currentShader->SendColor("Kd", currentObject->GetMaterial().mDiffuse);

			// Draw the Object
			currentObject->Bind();
				glDrawElements(GL_TRIANGLES, currentObject->GetIndexCount(), GL_UNSIGNED_INT, 0);
			currentObject->UnBind();
		}
		currentShader->UnBind();
		
		// Add DebugObject number to total
		mEntityNumber += mVAOList.size();

		// Clear the vector for next frame
		mVAOList.clear();
	}
}